#include <bits/stdc++.h>

using namespace std;

const int maxn=30005;
const int maxp=200;

int pri[maxp];
bool notprime[maxp+5];
inline int build_pri(){
    int cnt_prime=0;
    for(int i=2;i<=maxp;i++){
        if(!notprime[i]) pri[cnt_prime++]=i;
        for(int j=0;j<cnt_prime;j++){
            notprime[i*pri[j]]=1;
            if(i%pri[j]==0) break;
        }
    }
    return cnt_prime;
}

int tot;
int id[maxp+5][maxp+5][3];
inline void build_id(const int &cnt_prime){
    for(int z=0;z<3;z++)
        for(int i=0;i<cnt_prime;i++)
            for(int j=0;j<cnt_prime;j++)
                id[pri[i]][pri[j]][z]=++tot;
}

vector<int> dvi[maxp+5];
int val[3];
const int maxdn=70005;
const int maxm=4000005;
int g[maxdn],h[maxdn],G[maxdn];
int v[maxm],nxt[maxm],c[maxm],en=2;
inline void build_dvi(const int &cnt_prime){
    for(int i=2;i<=200;i++)
        for(int j=0;j<cnt_prime;j++)
            if(i%pri[j]==0) dvi[i].push_back(pri[j]);
}
inline void addEdge(const int &x,const int &y,const int &z){
    v[en]=y;nxt[en]=g[x];c[en]=z;g[x]=en++;
    v[en]=x;nxt[en]=g[y];c[en]=0;g[y]=en++;
}
inline void build_edges(const int &p,const bool &b){
    for(int i=0;i<3;i++)
        for(int j=i+1;j<3;j++)
            for(int x=0;x<dvi[val[i]].size();x++)
                for(int y=0;y<dvi[val[j]].size();y++)
                    if(b) addEdge(p,id[dvi[val[i]][x]][dvi[val[i]][y]][i+j],1);
                    else addEdge(id[dvi[val[i]][x]][dvi[val[i]][y]][i+j],p,1);
}

int S,T;
int q[maxdn];
/*bool bfs(){
    memset(dis,-1,sizeof(dis));
    int f,r;
    f=r=0;
    memcpy(G,g,sizeof(g));
    dis[S]=0;
    for(q[r++]=S;f<r;f++){
        const int &cur=q[f];
        for(int j=g[cur];j;j=nxt[j]){
            const int &tar=v[j];
            if(!c[j]) continue;
            if(~dis[tar]) continue;
            dis[tar]=dis[cur]+1;
            q[r++]=tar;
        }
    }
    return ~dis[T];
}
int dfs(int p,int flow){
    int alpha,fl;
    alpha=flow;
    if(p==T) return flow;
    for(int &j=G[p];j;j=nxt[j]){
        const int &tar=v[j];
        if(c[j]&&dis[tar]==dis[p]+1&&(fl=dfs(tar,min(c[j],alpha)))){
            alpha-=fl;
            c[j]-=fl;
            c[j^1]+=fl;
        }
        if(!alpha) break;
    }
    return flow-alpha;
}*/

bool bfs()
{
	int head=0,tail=1;
	memset(h,-1,sizeof(h));
	q[0]=0;h[0]=0;
	while(head!=tail)
	{
		int x=q[head];head++;
		for(int i=g[x];i;i=nxt[i])
			if(h[v[i]]==-1&&c[i])
			{
				h[v[i]]=h[x]+1;
				q[tail++]=v[i];
			}
	}
	return h[T]!=-1;
}
int dfs(int x,int f)
{
	if(x==T)return f;
	int w,used=0;
	for(int i=g[x];i;i=nxt[i])
		if(h[v[i]]==h[x]+1)
		{
			w=dfs(v[i],min(c[i],f-used));
			c[i]-=w;c[i^1]+=w;used+=w;
			if(used==f)return f;
		}
	if(!used)h[x]=-1;
	return used;
}

int main(){
    int n1,n2,cnt,ans;
    cnt=build_pri();
    build_id(cnt);
    build_dvi(cnt);

    scanf("%d%d",&n1,&n2);
    S=++tot;
    T=++tot;
    for(int i=1;i<=n1;i++){
        scanf("%d%d%d",val,val+1,val+2);
        addEdge(S,++tot,1);
        build_edges(tot,1);
    }
    for(int i=1;i<=n2;i++){
        scanf("%d%d%d",val,val+1,val+2);
        addEdge(++tot,T,1);
        build_edges(tot,0);
    }
    ans=0;
    while(bfs())
        ans+=dfs(S,~0U>>1);
    /*printf("%d\n",dinic());*/
    return 0;
}
